package com.yc.http.v1.impl;

import com.yc.http.v1.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class TomcatImpl implements Tomcat {

    public static final String WEB_ROOT = "D:/_文件柜/123/0508/天下行租车/";
    // Servlet容器
    public static Map<String,HttpServlet> servletMap = new HashMap<>();
    // 会话容器
    public static Map<String, HttpSession> sessionMap = new ConcurrentHashMap<>();
    // hashMap 不安全
    // hashtable 安全
    // concurrentHashMap 安全   更好
    // 初始化Servlet 容器
    static {
        // 省略的类扫描
        servletMap.put("/hello.s", new HelloWorldServlet());
        servletMap.put("/redirect.s", new RedirectServlet());
        servletMap.put("/cookie.s", new CookieServlet());
        servletMap.put("/session.s", new SessionServlet());
        servletMap.put("/login.s", new LoginServlet());
        servletMap.put("/logout.s", new LogoutServlet());
        servletMap.put("/myinfo.s", new getLoginedUserServlet());
    }
    public static void main(String[] args) {
        // 定时器
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("会话扫描: " + System.currentTimeMillis());
                final Iterator<Map.Entry<String, HttpSession>> iterator = sessionMap.entrySet().iterator();
                while(iterator.hasNext()){
                    final Map.Entry<String, HttpSession> next = iterator.next();
                    final HttpSession session = next.getValue();
                    long time = System.currentTimeMillis() - session.getLastAccessedTime();
                    // 判断超时
                    if(time >= 1000 * 60){
                        System.out.println("移除会话:" + next.getKey());
                        iterator.remove();
                    }
                }
            }
        }, 0, 1000 * 60);
        new TomcatImpl().start(80);
    }
    @Override
    public void start(int port) {
        ServerSocket server = null;
        try {
            server = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (true) {
            try {
                final Socket socket = server.accept();
                final HttpServletRequest request = buildRequest(socket);
                final HttpServletResponse response = buildResponse(socket, request);
                if(isStaticRequest(request)){
                    // 静态请求
                    processStaticRequest(request, response);
                } else if(isServletRequest(request)){
                    // 动态请求
                    String uri = request.getRequestURI();
                    if(uri.contains("?")){
                        uri = uri.substring(0, uri.indexOf("?"));
                    }
                    HttpServlet servlet = servletMap.get(uri);
                    // servlet 设置响应内容
                    servlet.service(request,response);
                    // 响应对象将内容推送给客户端
                    response.flushBuffer();
                } else {
                    // 404
                }
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public HttpServletRequest buildRequest(Socket socket) {
        try {
            return new HttpServletRequestImpl(socket);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public HttpServletResponse buildResponse(Socket socket, HttpServletRequest request) {
        return new HttpServletResponseImpl(socket, request);
    }

    @Override
    public boolean isStaticRequest(HttpServletRequest request) {
        // 判断文件是否存在
        String filepath = WEB_ROOT + request.getRequestURI();
        return new File(filepath).exists();
    }

    @Override
    public boolean isServletRequest(HttpServletRequest request) {
        // 判断容器中是否包含该地址对应的Servlet对象
        String uri = request.getRequestURI();
        if(uri.contains("?")){
            uri = uri.substring(0, uri.indexOf("?"));
        }
        return servletMap.containsKey(uri);
    }

    @Override
    public boolean processStaticRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        final OutputStream out = response.getOutputStream();
        // 输出 hello world
        // 响应头行
        out.write(String.format("%s %s %s\n",
                request.getProtocol(), "200", "OK").getBytes());
        String contentType = getMimeType(request.getRequestURI());
        // 头域参数
        out.write(String.format("%s: %s\n",
                "Content-Type", contentType).getBytes());
        // 空行
        out.write(String.format("\n").getBytes());
        // 内容 body
        // 输出指定文件
        String filepath = WEB_ROOT + request.getRequestURI();
        try(FileInputStream fis = new FileInputStream(filepath)){
            byte[] bytes = new byte[1024];
            int count;
            while((count = fis.read(bytes))>-1){
                out.write(bytes, 0, count);
            }
        }
//        out.write(String.format("<h1>hello world</h1>\n").getBytes());
        return false;
    }

    @Override
    public boolean processServletRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        return false;
    }

    @Override
    public String getMimeType(String path) {
        final String suffix = path.replaceAll(".*/\\w+\\.(\\w+)\\??.*", "$1");
        System.out.println("suffix = " + suffix);
        if("js".equals(suffix)){
            return "application/javascript;charset=utf-8";
        } else if("css".equals(suffix)){
            return "text/css;charset=utf-8";
        } else if("jpg".equals(suffix)){
            return "image/jpg";
        } else {
            return "text/html;charset=utf-8";
        }
    }

    @Override
    public HttpServlet getServlet(HttpServletRequest request) {
        return null;
    }

    @Override
    public void createSession(HttpServletRequest request, HttpServletResponse response) {

    }

    @Override
    public void stop() {

    }
}
